home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
BBS_UTL
/
STLTH22
/
SYSCHECK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-09
|
5KB
|
173 lines
/*
syscheck.c
Stealth Bomber Version 2.2
Kevin Dean
Fairview Mall P.O. Box 55074
1800 Sheppard Avenue East
Willowdale, Ontario
CANADA M2J 5B9
CompuServe ID: 76336,3114
February 10, 1992
This module checks the computer system for viruses by looking for
inconsistencies in the operating system. It does so by comparing DOS and BIOS
memory, checking for interrupts set beyond the code space of the program, and
checking interrupts for hijacking code.
This code is public domain.
*/
#if (defined(M_I86SM) || defined(M_I86MM) || defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM)) && !defined(_MSC_VER) && !defined(_QC)
#define _MSC_VER
#endif
#if !defined(__BORLANDC__) && !defined(__TURBOC__) && !defined(_MSC_VER) && !defined(_QC)
#error Unknown compiler.
#endif
#include <bios.h>
#include <dos.h>
#include <stdlib.h>
#include "vircheck.h"
#include "dosmcb.h"
#if defined(__BORLANDC__) || defined(__TURBOC__)
typedef
void interrupt (*intr_ptr)();
#elif defined(_MSC_VER) || defined(_QC)
typedef
void (interrupt far *intr_ptr)();
#define getvect _dos_getvect
#define setvect _dos_setvect
#if !defined(MK_FP)
#define MK_FP(seg, off) ((void far *)(((unsigned long)(seg) << 16) | (off)))
#endif
#define biosmemory _bios_memsize
#endif
/***/
/* Determine true segment address of pointer and check for wrap around memory. */
unsigned ptrseg(void far * ptr)
{
unsigned pseg;
if ((pseg = FP_SEG(ptr) + (FP_OFF(ptr) >> 4)) < FP_SEG(ptr))
/* Pointer points beyond standard 1M memory. */
pseg = 0xFFFF;
return (pseg);
}
/***/
/* Validate interrupt; make sure not beyond code space and not hijacked. */
static unsigned validateintr(int intrnum, unsigned memlimit)
{
/* Assume interrupt is valid. */
unsigned result = STEALTH_OK;
union
{
intr_ptr iptr; /* Interrupt pointer. */
const byte far *codeptr; /* Pointer to interrupt; treat as data. */
} i;
unsigned iseg; /* Adjusted segment of i.iptr. */
intr_ptr target; /* Target of hijacked interrupt. */
/* Get interrupt and adjusted segment. */
i.iptr = getvect(intrnum);
iseg = ptrseg(i.iptr);
/* Interrupt pointer invalid if between PSP and memory limit. */
if (iseg >= _psp && iseg < memlimit)
result |= STEALTH_INTR_ERR;
/* Check beginning of interrupt code for suspicious instructions. */
switch (*i.codeptr)
{
case 0xEA: /* JMP FAR <addr>. */
case 0x9A: /* CALL FAR <addr>. */
target = *(intr_ptr far *)(i.codeptr + 1);
result |= STEALTH_DOS_HIJACKED;
break;
case 0x2E: /* CS segment prefix. */
switch (*(const word far *)(i.codeptr + 1))
{
case 0x2EFF: /* JMP FAR CS:[addr]. */
case 0x1EFF: /* CALL FAR CS:[addr]. */
target = *(intr_ptr far *)MK_FP(FP_SEG(i.codeptr), *(word far *)(i.codeptr + 3));
result |= STEALTH_DOS_HIJACKED;
break;
}
}
if (result & STEALTH_DOS_HIJACKED)
{
MCB far *intrmcb;
MCB far *targetmcb;
/* Determine MCB's that own the interrupt and the target of the redirection. */
intrmcb = mcb_owner(i.codeptr);
targetmcb = mcb_owner(target);
/* Redirection is valid if it falls within the same MCB or falls outside memory limit. */
if (intrmcb == targetmcb || ptrseg(target) >= memlimit)
result &= ~STEALTH_DOS_HIJACKED;
}
return (result);
}
/***/
/* Perform anti-virus system check. */
unsigned stealth_sys_check(void)
{
/* Assume system passes all tests. */
unsigned result = STEALTH_OK;
MCB far *mcb; /* Memory control block pointer. */
unsigned biosmem; /* Memory in paragraphs according to BIOS. */
unsigned dosmem; /* Memory in paragraphs according to DOS. */
unsigned memlimit; /* Limit of useable memory. */
biosmem = (unsigned)biosmemory() * 64;
/* Find last memory control block. */
for (mcb = getmcb(); mcb->id != 0x5A; mcb = nextmcb(mcb));
dosmem = FP_SEG(mcb) + mcb->size + 1;
/* DOS memory extenders may show more memory than BIOS and some versions of DOS may differ by up to 1k from BIOS memory. */
if (biosmem > dosmem + 64)
result |= STEALTH_DOS_MEM_ERR;
/* Assume BIOS memory goes at least to 640k limit (may have been modified by virus). */
memlimit = max((unsigned)0xA000, biosmem);
memlimit = max(memlimit, dosmem);
result |= validateintr(0x21, memlimit); /* DOS function interrupt. */
result |= validateintr(0x24, memlimit); /* Critical error interrupt. */
result |= validateintr(0x25, memlimit); /* Absolute disk read interrupt. */
result |= validateintr(0x26, memlimit); /* Absolute disk write interrupt. */
result |= validateintr(0x1C, memlimit); /* User timer interrupt. */
result |= validateintr(0x28, memlimit); /* DOS OK interrupt. */
return (result);
}